package handler

import (
	"encoding/json"
	"fmt"
	"net/http"
	"sync"
	"time"

	"enterprise-wechat-pay-sdk/config"

	"github.com/gin-gonic/gin"
)

// TokenResponse access_token响应结构
type TokenResponse struct {
	ErrCode     int    `json:"errcode"`
	ErrMsg      string `json:"errmsg"`
	AccessToken string `json:"access_token"`
	ExpiresIn   int    `json:"expires_in"`
}

// TokenCache access_token缓存结构
type TokenCache struct {
	AccessToken string
	ExpiresAt   time.Time
	Mutex       sync.RWMutex
}

var tokenCache = &TokenCache{}

// GetAccessToken 获取access_token
func GetAccessToken(c *gin.Context) {
	token, err := getAccessToken()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"errcode": -1,
			"errmsg":  fmt.Sprintf("获取access_token失败: %v", err),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"errcode":      0,
		"errmsg":       "ok",
		"access_token": token,
	})
}

// getAccessToken 获取access_token（带缓存）
func getAccessToken() (string, error) {
	// 先尝试从缓存获取
	tokenCache.Mutex.RLock()
	if tokenCache.AccessToken != "" && time.Now().Before(tokenCache.ExpiresAt) {
		token := tokenCache.AccessToken
		tokenCache.Mutex.RUnlock()
		return token, nil
	}
	tokenCache.Mutex.RUnlock()

	// 缓存不存在或已过期，重新获取
	tokenCache.Mutex.Lock()
	defer tokenCache.Mutex.Unlock()

	// 双重检查，避免并发请求重复获取
	if tokenCache.AccessToken != "" && time.Now().Before(tokenCache.ExpiresAt) {
		return tokenCache.AccessToken, nil
	}

	// 请求企业微信接口获取access_token
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s",
		config.GlobalConfig.Wechat.CorpID,
		config.GlobalConfig.Wechat.CorpSecret)
	fmt.Println(url)
	fmt.Println(config.GlobalConfig.Wechat.CorpID)
	fmt.Println(config.GlobalConfig.Wechat.CorpSecret)
	resp, err := http.Get(url)
	if err != nil {
		return "", fmt.Errorf("请求access_token失败: %v", err)
	}
	defer resp.Body.Close()

	var result TokenResponse
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return "", fmt.Errorf("解析access_token响应失败: %v", err)
	}

	if result.ErrCode != 0 {
		return "", fmt.Errorf("获取access_token失败: %s", result.ErrMsg)
	}

	// 更新缓存
	tokenCache.AccessToken = result.AccessToken
	// 提前5分钟过期，避免临界点问题
	tokenCache.ExpiresAt = time.Now().Add(time.Duration(result.ExpiresIn-300) * time.Second)

	return result.AccessToken, nil
}
